home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 5
/
Aminet 5 - March 1995.iso
/
Aminet
/
game
/
role
/
Ang261Lib.lha
/
src
/
moria1.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-10-22
|
75KB
|
2,840 lines
/*
* moria1.c: misc code, mainly to handle player movement, inventory, etc.
*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
* This software may be copied and distributed for educational, research, and
* not for profit purposes provided that this copyright and statement are
* included in all such copies.
*/
#include <stdio.h>
#include <ctype.h>
#include "constant.h"
#include "config.h"
#include "types.h"
#include "externs.h"
#include "monster.h"
#ifdef USG
#ifndef ATARIST_MWC
#include <string.h>
#else
char *strcat();
int strlen();
#endif
#else
#include <strings.h>
#endif
/* Lets do all prototypes correctly.... -CWS */
#ifndef NO_LINT_ARGS
#ifdef __STDC__
static void inven_screen(int);
static char map_roguedir(int);
static void sub1_move_light(int, int, int, int);
static void sub3_move_light(int, int, int, int);
static int see_wall(int, int, int);
static int see_nothing(int, int, int);
#else
static void inven_screen();
static char map_roguedir();
static void sub1_move_light();
static void sub3_move_light();
static int see_wall();
static int see_nothing();
#endif
#endif
/* Changes speed of monsters relative to player -RAK-
* Note: When the player is sped up or slowed down, I simply change the
* speed of all the monsters. This greatly simplified the logic.
*****
* No LONGER! A change in player speed only affect player's speed. The new
* code in movement_rate() allows monsters to have attacks in correct
* proportions, and still uses only int math -CFT
*/
void
change_speed(num)
register int num;
{
py.flags.speed += num;
py.flags.status |= PY_SPEED;
}
/* Player bonuses -RAK- */
/* When an item is worn or taken off, this re-adjusts the player
* bonuses. Factor=1 : wear; Factor=-1 : removed
*****
* Only calculates properties with cumulative effect. Properties that depend
* on everything being worn are recalculated by calc_bonuses() -CJS -
*/
void
py_bonuses(t_ptr, factor)
register inven_type *t_ptr;
register int factor;
{
register int i, amount;
amount = t_ptr->p1 * factor;
if (t_ptr->flags & TR_STATS) {
for (i = 0; i < 6; i++)
if ((1 << i) & t_ptr->flags)
bst_stat(i, amount);
}
if (TR_SEARCH & t_ptr->flags) {
py.misc.srh += amount;
py.misc.fos -= amount;
}
if (TR_STEALTH & t_ptr->flags)
py.misc.stl += amount;
if (TR_SPEED & t_ptr->flags) {
if ((t_ptr->tval == TV_RING) &&
!stricmp("Speed",
object_list[t_ptr->index].name) &&
(t_ptr->p1 > 0))
if ((inventory[INVEN_RIGHT].tval == TV_RING) &&
!stricmp("Speed",
object_list[inventory[INVEN_RIGHT].index].name) &&
(inventory[INVEN_RIGHT].p1 > 0) &&
(inventory[INVEN_LEFT].tval == TV_RING) &&
!stricmp("Speed",
object_list[inventory[INVEN_LEFT].index].name) &&
(inventory[INVEN_RIGHT].p1 > 0))
return;
change_speed(-amount);
}
if (TR_INFRA & t_ptr->flags)
py.flags.see_infra += amount;
}
/* Recalculate the effect of all the stuff we use. -CJS- */
/* Also initialise race intrinsics SM */
void
calc_bonuses()
{
register int32u item_flags;
register int32u item_flags2;
int old_dis_ac;
register struct flags *p_ptr;
register struct misc *m_ptr;
register inven_type *i_ptr;
register int i;
p_ptr = &py.flags;
m_ptr = &py.misc;
if (p_ptr->slow_digest)
p_ptr->food_digested++;
if (p_ptr->regenerate)
p_ptr->food_digested -= 3;
if (py.misc.prace == 9)
p_ptr->see_inv = TRUE;
else
p_ptr->see_inv = FALSE;
p_ptr->teleport = FALSE;
if (py.misc.prace == 4)
p_ptr->free_act = TRUE;
else
p_ptr->free_act = FALSE;
p_ptr->slow_digest = FALSE;
p_ptr->aggravate = FALSE;
if (py.misc.prace == 7)
p_ptr->sustain_str = TRUE;
else
p_ptr->sustain_str = FALSE;
p_ptr->sustain_int = FALSE;
p_ptr->sustain_wis = FALSE;
if (py.misc.prace == 8)
p_ptr->sustain_con = TRUE;
else
p_ptr->sustain_con = FALSE;
if (py.misc.prace == 3)
p_ptr->sustain_dex = TRUE;
else
p_ptr->sustain_dex = FALSE;
p_ptr->sustain_chr = FALSE;
p_ptr->fire_resist = FALSE;
p_ptr->acid_resist = FALSE;
p_ptr->cold_resist = FALSE;
p_ptr->regenerate = FALSE;
p_ptr->lght_resist = FALSE;
if (py.misc.prace == 9)
p_ptr->ffall = TRUE;
else
p_ptr->ffall = FALSE;
p_ptr->poison_resist = FALSE;
p_ptr->hold_life = FALSE;
p_ptr->telepathy = FALSE;
p_ptr->fire_im = FALSE;
p_ptr->acid_im = FALSE;
p_ptr->poison_im = FALSE;
p_ptr->cold_im = FALSE;
p_ptr->light_im = FALSE;
p_ptr->light = FALSE;
p_ptr->confusion_resist = FALSE;
p_ptr->sound_resist = FALSE;
if (py.misc.prace == 2)
p_ptr->light_resist = TRUE;
else
p_ptr->light_resist = FALSE;
if (py.misc.prace == 6)
p_ptr->dark_resist = TRUE;
else
p_ptr->dark_resist = FALSE;
p_ptr->chaos_resist = FALSE;
p_ptr->disenchant_resist = FALSE;
p_ptr->shards_resist = FALSE;
p_ptr->nexus_resist = FALSE;
if (py.misc.prace == 5)
p_ptr->blindness_resist = TRUE;
else
p_ptr->blindness_resist = FALSE;
p_ptr->nether_resist = FALSE;
p_ptr->fear_resist = FALSE;
old_dis_ac = m_ptr->dis_ac;
m_ptr->ptohit = tohit_adj(); /* Real To Hit */
m_ptr->ptodam = todam_adj(); /* Real To Dam */
m_ptr->ptoac = toac_adj(); /* Real To AC */
m_ptr->pac = 0; /* Real AC */
m_ptr->dis_th = m_ptr->ptohit; /* Display To Hit */
m_ptr->dis_td = m_ptr->ptodam; /* Display To Dam */
m_ptr->dis_ac = 0; /* Display AC */
m_ptr->dis_tac = m_ptr->ptoac; /* Display To AC */
for (i = INVEN_WIELD; i <= INVEN_LIGHT; i++) {
i_ptr = &inventory[i];
if (i_ptr->tval != TV_NOTHING) {
if ((TR_CURSED & i_ptr->flags) == 0) {
m_ptr->pac += i_ptr->ac;
m_ptr->dis_ac += i_ptr->ac;
}
m_ptr->ptohit += i_ptr->tohit;
if (i_ptr->tval != TV_BOW) /* Bows can't damage. -CJS- */
m_ptr->ptodam += i_ptr->todam;
m_ptr->ptoac += i_ptr->toac;
if (known2_p(i_ptr)) {
m_ptr->dis_th += i_ptr->tohit;
if (i_ptr->tval != TV_BOW)
m_ptr->dis_td += i_ptr->todam; /* Bows can't damage. -CJS- */
m_ptr->dis_tac += i_ptr->toac;
}
}
}
if (py.misc.pclass == 2) {
i_ptr = &inventory[INVEN_WIELD];
if (!(i_ptr->flags2 & TR_BLESS_BLADE) && /* blessed blade == no penalty -CWS */
(i_ptr->tval == TV_SWORD || i_ptr->tval == TV_POLEARM)) {
m_ptr->ptohit -= 2;
m_ptr->ptodam -= 2;
m_ptr->dis_th -= 2;
m_ptr->dis_td -= 2;
}
}
if (weapon_heavy)
m_ptr->dis_th += (py.stats.use_stat[A_STR] * 15 -
inventory[INVEN_WIELD].weight);
/* don't forget stun adj, or we'll get incorrect values... -CFT */
if (p_ptr->stun > 50) {
m_ptr->ptohit -= 20;
m_ptr->dis_th -= 20;
m_ptr->ptodam -= 20;
m_ptr->dis_td -= 20;
} else if (p_ptr->stun > 0) {
m_ptr->ptohit -= 5;
m_ptr->dis_th -= 5;
m_ptr->ptodam -= 5;
m_ptr->dis_td -= 5;
}
/* Add in temporary spell increases */
/*
* these changed from pac to ptoac, since mana now affected by high pac (to
* sim. encumberence), and these really should be magical bonuses -CFT
*/
if (p_ptr->status & PY_INVULN) {
m_ptr->ptoac += 100;
m_ptr->dis_tac += 100;
}
if (p_ptr->status & PY_BLESSED) { /* changed to agree w/ code in
* dungeon()... -CFT */
m_ptr->ptoac += 5;
m_ptr->dis_tac += 5;
m_ptr->ptohit += 10;
m_ptr->dis_th += 10;
}
if (p_ptr->shield > 0) {
m_ptr->ptoac += 50;
m_ptr->dis_tac += 50;
}
if (p_ptr->detect_inv > 0)
p_ptr->see_inv = TRUE;
if (p_ptr->status & PY_HERO) { /* now agrees w/ code in dungeon() -CFT */
m_ptr->ptohit += 12;
m_ptr->dis_th += 12;
}
if (p_ptr->status & PY_SHERO) {/* now agrees w/ code in dungeon() -CFT */
m_ptr->ptohit += 24;
m_ptr->dis_th += 24;
m_ptr->ptoac -= 10; /* berserk, so not being careful... -CFT */
m_ptr->dis_tac -= 10;
}
m_ptr->dis_ac += m_ptr->dis_tac; /* this moved from above, so it will
* show ac adjustments from spells...
* -CFT */
/* can't print AC here because might be in a store */
p_ptr->status |= PY_ARMOR; /* This was in an if, but I want to be
* sure ac is shown properly... -CFT */
item_flags = 0L;
i_ptr = &inventory[INVEN_WIELD];
for (i = INVEN_WIELD; i <= INVEN_LIGHT; i++) {
item_flags |= i_ptr->flags;
i_ptr++;
}
item_flags2 = 0L;
i_ptr = &inventory[INVEN_WIELD];
for (i = INVEN_WIELD; i <= INVEN_LIGHT; i++) {
item_flags2 |= i_ptr->flags2;
i_ptr++;
}
if (TR_SLOW_DIGEST & item_flags)
p_ptr->slow_digest = TRUE;
if (TR_AGGRAVATE & item_flags)
p_ptr->aggravate = TRUE;
if (TR_TELEPORT & item_flags)
p_ptr->teleport = TRUE;
if (TR_REGEN & item_flags)
p_ptr->regenerate = TRUE;
if (TR_RES_FIRE & item_flags)
p_ptr->fire_resist = TRUE;
if (TR_RES_ACID & item_flags)
p_ptr->acid_resist = TRUE;
if (TR_RES_COLD & item_flags)
p_ptr->cold_resist = TRUE;
if (TR_POISON & item_flags)
p_ptr->poison_resist = TRUE;
if (TR_HOLD_LIFE & item_flags2)
p_ptr->hold_life = TRUE;
if (TR_TELEPATHY & item_flags2)
p_ptr->telepathy = TRUE;
if (TR_IM_FIRE & item_flags2)
p_ptr->fire_im = TRUE;
if (TR_IM_ACID & item_flags2)
p_ptr->acid_im = TRUE;
if (TR_IM_COLD & item_flags2)
p_ptr->cold_im = TRUE;
if (TR_IM_LIGHT & item_flags2)
p_ptr->light_im = TRUE;
if (TR_IM_POISON & item_flags2)
p_ptr->poison_im = TRUE;
if (TR_LIGHT & item_flags2)
p_ptr->light = TRUE;
if (TR_FREE_ACT & item_flags)
p_ptr->free_act = TRUE;
if (TR_SEE_INVIS & item_flags)
p_ptr->see_inv = TRUE;
if (TR_RES_LIGHT & item_flags)
p_ptr->lght_resist = TRUE;
if (TR_FFALL & item_flags)
p_ptr->ffall = TRUE;
if (TR_RES_CONF & item_flags2)
p_ptr->confusion_resist = TRUE;
if (TR_RES_SOUND & item_flags2)
p_ptr->sound_resist = TRUE;
if (TR_RES_LT & item_flags2)
p_ptr->light_resist = TRUE;
if (TR_RES_DARK & item_flags2)
p_ptr->dark_resist = TRUE;
if (TR_RES_CHAOS & item_flags2)
p_ptr->chaos_resist = TRUE;
if (TR_RES_DISENCHANT & item_flags2)
p_ptr->disenchant_resist = TRUE;
if (TR_RES_SHARDS & item_flags2)
p_ptr->shards_resist = TRUE;
if (TR_RES_NEXUS & item_flags2)
p_ptr->nexus_resist = TRUE;
if (TR_RES_BLIND & item_flags2)
p_ptr->blindness_resist = TRUE;
if (TR_RES_NETHER & item_flags2)
p_ptr->nether_resist = TRUE;
if (TR_RES_FEAR & item_flags2)
p_ptr->fear_resist = TRUE;
i_ptr = &inventory[INVEN_WIELD];
for (i = INVEN_WIELD; i < INVEN_LIGHT; i++) {
if (TR_SUST_STAT & i_ptr->flags)
switch (i_ptr->p1) {
case 1:
p_ptr->sustain_str = TRUE;
break;
case 2:
p_ptr->sustain_int = TRUE;
break;
case 3:
p_ptr->sustain_wis = TRUE;
break;
case 4:
p_ptr->sustain_con = TRUE;
break;
case 5:
p_ptr->sustain_dex = TRUE;
break;
case 6:
p_ptr->sustain_chr = TRUE;
break;
case 10: /* :-) ~Ludwig the Hacker!!! */
p_ptr->sustain_str = TRUE;
p_ptr->sustain_int = TRUE;
p_ptr->sustain_wis = TRUE;
p_ptr->sustain_con = TRUE;
p_ptr->sustain_dex = TRUE;
p_ptr->sustain_chr = TRUE;
break;
default:
break;
}
i_ptr++;
}
if (p_ptr->slow_digest)
p_ptr->food_digested--;
if (p_ptr->regenerate)
p_ptr->food_digested += 3;
if (class[py.misc.pclass].spell == MAGE) {
calc_mana(A_INT);
} else if (class[py.misc.pclass].spell == PRIEST) {
calc_mana(A_WIS);
}
}
/* Displays inventory items from r1 to r2 -RAK- */
/*
* Designed to keep the display as far to the right as possible. The -CJS-
* parameter col gives a column at which to start, but if the display does
* not fit, it may be moved left. The return value is the left edge used.
*/
int
show_inven(r1, r2, weight, col, test)
register int r1, r2;
int weight, col;
int (*test) ();
{
register int i, j, k;
int total_weight, len, l, lim;
bigvtype tmp_val;
vtype out_val[23];
len = 79 - col;
if (weight)
lim = 68;
else
lim = 76;
for (i = 0; i < 23; i++)
out_val[i][0] = '\0';
k = 0;
for (i = r1; i <= r2; i++) {
if (test) {
if ((*test) (object_list[inventory[i].index].tval)) {
objdes(tmp_val, &inventory[i], TRUE);
tmp_val[lim] = 0; /* Truncate if too long. */
(void)sprintf(out_val[i], " %c) %s", 'a' + i, tmp_val);
l = strlen(out_val[i]);
if (weight)
l += 9;
if (l > len)
len = l;
k++;
}
} else {
objdes(tmp_val, &inventory[i], TRUE);
tmp_val[lim] = 0; /* Truncate if too long. */
(void)sprintf(out_val[i], " %c) %s", 'a' + i, tmp_val);
l = strlen(out_val[i]);
if (weight)
l += 9;
if (l > len)
len = l;
k++;
}
}
col = 79 - len;
if (col < 0)
col = 0;
j = 0;
for (i = r1; (i <= r2) && k; i++) {
if (out_val[i][0]) {
k--;
/* don't need first two spaces if in first column */
if (col == 0)
prt(&out_val[i][2], 1 + j, col);
else
prt(out_val[i], 1 + j, col);
if (weight) {
total_weight = inventory[i].weight * inventory[i].number;
(void)sprintf(tmp_val, "%3d.%d lb",
(total_weight) / 10, (total_weight) % 10);
prt(tmp_val, 1 + j, 71);
}
j++;
}
}
erase_line(1+j,col);
return col;
}
/* Return a string describing how a given equipment item is carried. -CJS- */
const char *
describe_use(i)
register int i;
{
register const char *p;
switch (i) {
case INVEN_WIELD:
p = "wielding";
break;
case INVEN_HEAD:
p = "wearing on your head";
break;
case INVEN_NECK:
p = "wearing around your neck";
break;
case INVEN_BODY:
p = "wearing on your body";
break;
case INVEN_ARM:
p = "wearing on your arm";
break;
case INVEN_HANDS:
p = "wearing on your hands";
break;
case INVEN_RIGHT:
p = "wearing on your right hand";
break;
case INVEN_LEFT:
p = "wearing on your left hand";
break;
case INVEN_FEET:
p = "wearing on your feet";
break;
case INVEN_OUTER:
p = "wearing about your body";
break;
case INVEN_LIGHT:
p = "using to light the way";
break;
case INVEN_AUX:
p = "holding ready by your side";
break;
default:
p = "carrying in your pack";
break;
}
return p;
}
/* Displays equipment items from r1 to end -RAK- */
/* Keep display as far right as possible. -CJS- */
int
show_equip(weight, col)
int weight, col;
{
register int i, line;
int total_weight, l, len, lim;
register const char *prt1;
bigvtype prt2;
vtype out_val[INVEN_ARRAY_SIZE - INVEN_WIELD];
register inven_type *i_ptr;
line = 0;
len = 79 - col;
if (weight)
lim = 52;
else
lim = 60;
for (i = INVEN_WIELD; i < INVEN_ARRAY_SIZE; i++) {
i_ptr = &inventory[i];
if (i_ptr->tval != TV_NOTHING) {
switch (i) {
case INVEN_WIELD:
if (py.stats.use_stat[A_STR] * 15 < i_ptr->weight)
prt1 = "Just lifting";
else
prt1 = "Wielding";
break;
case INVEN_HEAD:
prt1 = "On head";
break;
case INVEN_NECK:
prt1 = "Around neck";
break;
case INVEN_BODY:
prt1 = "On body";
break;
case INVEN_ARM:
prt1 = "On arm";
break;
case INVEN_HANDS:
prt1 = "On hands";
break;
case INVEN_RIGHT:
prt1 = "On right hand";
break;
case INVEN_LEFT:
prt1 = "On left hand";
break;
case INVEN_FEET:
prt1 = "On feet";
break;
case INVEN_OUTER:
prt1 = "About body";
break;
case INVEN_LIGHT:
prt1 = "Light source";
break;
case INVEN_AUX:
prt1 = "Spare weapon";
break;
default:
prt1 = "Unknown value";
break;
}
objdes(prt2, &inventory[i], TRUE);
prt2[lim] = 0; /* Truncate if necessary */
(void)sprintf(out_val[line], " %c) %-14s: %s", line + 'a',
prt1, prt2);
l = strlen(out_val[line]);
if (weight)
l += 9;
if (l > len)
len = l;
line++;
}
}
col = 79 - len;
if (col < 0)
col = 0;
line = 0;
for (i = INVEN_WIELD; i < INVEN_ARRAY_SIZE; i++) {
i_ptr = &inventory[i];
if (i_ptr->tval != TV_NOTHING) {
/* don't need first two spaces when using whole screen */
if (col == 0)
prt(&out_val[line][2], line + 1, col);
else
prt(out_val[line], line + 1, col);
if (weight) {
total_weight = i_ptr->weight * i_ptr->number;
(void)sprintf(prt2, "%3d.%d lb",
(total_weight) / 10, (total_weight) % 10);
prt(prt2, line + 1, 71);
}
line++;
}
}
erase_line(line + 1, col);
return col;
}
/* Remove item from equipment list -RAK- */
void
takeoff(item_val, posn)
int item_val, posn;
{
register const char *p;
bigvtype out_val, prt2;
register inven_type *t_ptr;
equip_ctr--;
t_ptr = &inventory[item_val];
inven_weight -= t_ptr->weight * t_ptr->number;
py.flags.status |= PY_STR_WGT;
if (item_val == INVEN_WIELD || item_val == INVEN_AUX)
p = "Was wielding ";
else if (item_val == INVEN_LIGHT)
p = "Light source was ";
else
p = "Was wearing ";
objdes(prt2, t_ptr, TRUE);
if (posn >= 0)
(void)sprintf(out_val, "%s%s. (%c)", p, prt2, 'a' + posn);
else if (posn == -1)
(void)sprintf(out_val, "%s%s.", p, prt2);
msg_print(out_val);
if (item_val != INVEN_AUX) /* For secondary weapon */
py_bonuses(t_ptr, -1);
invcopy(t_ptr, OBJ_NOTHING);
}
/* Used to verify if this really is the item we wish to wear or read. */
int
verify(prompt, item)
const char *prompt;
int item;
{
bigvtype out_str, object;
objdes(object, &inventory[item], TRUE);
(void)sprintf(out_str, "%s %s? ", prompt, object);
return get_check(out_str);
}
/*
* All inventory commands (wear, exchange, take off, drop, inventory and
* equipment) are handled in an alternative command input mode, which accepts
* any of the inventory commands.
*
* It is intended that this function be called several times in succession, as
* some commands take up a turn, and the rest of moria must proceed in the
* interim. A global variable is provided, doing_inven, which is normally
* zero; however if on return from inven_command it is expected that
* inven_command should be called *again*, (being still in inventory command
* input mode), then doing_inven is set to the inventory command character
* which should be used in the next call to inven_command.
*
* On return, the screen is restored, but not flushed. Provided no flush of the
* screen takes place before the next call to inven_command, the inventory
* command screen is silently redisplayed, and no actual output takes place
* at all. If the screen is flushed before a subsequent call, then the player
* is prompted to see if we should continue. This allows the player to see
* any changes that take place on the screen during inventory command input.
*
* The global variable, screen_change, is cleared by inven_command, and set when
* the screen is flushed. This is the means by which inven_command tell if
* the screen has been flushed.
*
* The display of inventory items is kept to the right of the screen to minimize
* the work done to restore the screen afterwards. -CJS-
*/
/* Inventory command screen states. */
#define BLANK_SCR 0
#define EQUIP_SCR 1
#define INVEN_SCR 2
#define WEAR_SCR 3
#define HELP_SCR 4
#define WRONG_SCR 5
/* Keep track of the state of the inventory screen. */
static int scr_state, scr_left, scr_base;
static int wear_low, wear_high;
/* Draw the inventory screen. */
static void
inven_screen(new_scr)
int new_scr;
{
register int line = 0;
if (new_scr != scr_state) {
scr_state = new_scr;
switch (new_scr) {
case BLANK_SCR:
line = 0;
break;
case HELP_SCR:
if (scr_left > 52)
scr_left = 52;
prt(" e : list used equipment", 1, scr_left);
prt(" i : inventory of pack", 2, scr_left);
prt(" t : take off item", 3, scr_left);
prt(" w : wear or wield object", 4, scr_left);
prt(" x : exchange weapons", 5, scr_left);
prt(" d : drop object", 6, scr_left);
prt(" ESC: exit", 7, scr_left);
line = 7;
break;
case INVEN_SCR:
scr_left = show_inven(0, inven_ctr - 1, show_weight_flag, scr_left, 0);
line = inven_ctr;
break;
case WEAR_SCR:
scr_left = show_inven(wear_low, wear_high, show_weight_flag, scr_left, 0);
line = wear_high - wear_low + 1;
break;
case EQUIP_SCR:
scr_left = show_equip(show_equip_weight_flag, scr_left);
line = equip_ctr;
break;
}
if (line >= scr_base) {
scr_base = line + 1;
erase_line(scr_base, scr_left);
} else {
while (++line <= scr_base)
erase_line(line, scr_left);
}
}
}
/* This does all the work. */
void
inven_command(command)
int command;
{
register int slot = 0, item;
int tmp, tmp2, selecting, from, to, light_chg = FALSE;
const char *prompt, *swap, *disp, *string;
char which, query;
bigvtype prt1, prt2;
register inven_type *i_ptr;
inven_type tmp_obj;
free_turn_flag = TRUE;
save_screen();
/* Take up where we left off after a previous inventory command. -CJS- */
if (doing_inven) {
/* If the screen has been flushed, we need to redraw. If the command is a
* simple ' ' to recover the screen, just quit. Otherwise, check and see
* what the user wants.
*/
if (screen_change) {
if (command == ' ' || !get_check("Continuing with inventory command?")) {
doing_inven = FALSE;
return;
}
scr_left = 50;
scr_base = 0;
}
tmp = scr_state;
scr_state = WRONG_SCR;
inven_screen(tmp);
} else {
scr_left = 50;
scr_base = 0;
/* this forces exit of inven_command() if selecting is not set true */
scr_state = BLANK_SCR;
}
do {
if (isupper((int)command))
command = tolower((int)command);
/* Simple command getting and screen selection. */
selecting = FALSE;
switch (command) {
case 'i': /* Inventory */
if (inven_ctr == 0)
msg_print("You are not carrying anything.");
else
inven_screen(INVEN_SCR);
break;
case 'e': /* Equipment */
if (equip_ctr == 0)
msg_print("You are not using any equipment.");
else
inven_screen(EQUIP_SCR);
break;
case 't': /* Take off */
if (equip_ctr == 0)
msg_print("You are not using any equipment.");
/* don't print message restarting inven command after taking off
* something, it is confusing
*/
else if (inven_ctr >= INVEN_WIELD && !doing_inven)
msg_print("You will have to drop something first.");
else {
if (scr_state != BLANK_SCR)
inven_screen(EQUIP_SCR);
selecting = TRUE;
}
break;
case 'd': /* Drop */
if (inven_ctr == 0 && equip_ctr == 0)
msg_print("But you're not carrying anything.");
else if (cave[char_row][char_col].tptr != 0)
msg_print("There's no room to drop anything here.");
else {
selecting = TRUE;
if ((scr_state == EQUIP_SCR && equip_ctr > 0) || inven_ctr == 0) {
if (scr_state != BLANK_SCR)
inven_screen(EQUIP_SCR);
command = 'r'; /* Remove - or take off and drop. */
} else if (scr_state != BLANK_SCR)
inven_screen(INVEN_SCR);
}
break;
case 'w': /* Wear/wield */
for (wear_low = 0;
wear_low < inven_ctr && inventory[wear_low].tval > TV_MAX_WEAR;
wear_low++);
for (wear_high = wear_low;
wear_high < inven_ctr && inventory[wear_high].tval >= TV_MIN_WEAR;
wear_high++);
wear_high--;
if (wear_low > wear_high)
msg_print("You have nothing to wear or wield.");
else {
if (scr_state != BLANK_SCR && scr_state != INVEN_SCR)
inven_screen(WEAR_SCR);
selecting = TRUE;
}
break;
case 'x':
if (inventory[INVEN_WIELD].tval == TV_NOTHING &&
inventory[INVEN_AUX].tval == TV_NOTHING)
msg_print("But you are wielding no weapons.");
else if (TR_CURSED & inventory[INVEN_WIELD].flags) {
objdes(prt1, &inventory[INVEN_WIELD], FALSE);
(void)sprintf(prt2,
"The %s you are wielding appears to be cursed.", prt1);
msg_print(prt2);
} else {
free_turn_flag = FALSE;
tmp_obj = inventory[INVEN_AUX];
inventory[INVEN_AUX] = inventory[INVEN_WIELD];
inventory[INVEN_WIELD] = tmp_obj;
if (scr_state == EQUIP_SCR)
scr_left = show_equip(show_weight_flag, scr_left);
py_bonuses(&inventory[INVEN_AUX], -1); /* Subtract bonuses */
py_bonuses(&inventory[INVEN_WIELD], 1); /* Add bonuses */
if (inventory[INVEN_WIELD].tval != TV_NOTHING) {
(void)strcpy(prt1, "Primary weapon : ");
objdes(prt2, &inventory[INVEN_WIELD], TRUE);
msg_print(strcat(prt1, prt2));
} else
msg_print("No primary weapon.");
/* this is a new weapon, so clear the heavy flag */
/* no, don't; the check_strength will clear it if it needs to be cleared
weapon_heavy = FALSE; */
check_strength();
}
break;
case ' ': /* Dummy command to return again to main
* prompt. */
break;
case '?':
inven_screen(HELP_SCR);
break;
default:
/* Nonsense command */
bell();
break;
}
/* Clear the doing_inven flag here, instead of at beginning, so that can
* use it to control when messages above appear.
*/
doing_inven = 0;
/* Keep looking for objects to drop/wear/take off/throw off */
which = 'z';
while (selecting && free_turn_flag) {
swap = "";
if (command == 'w') {
from = wear_low;
to = wear_high;
prompt = "Wear/Wield";
} else {
from = 0;
if (command == 'd') {
to = inven_ctr - 1;
prompt = "Drop";
if (equip_ctr > 0)
swap = ", / for Equip";
} else {
to = equip_ctr - 1;
if (command == 't')
prompt = "Take off";
else { /* command == 'r' */
prompt = "Throw off";
if (inven_ctr > 0)
swap = ", / for Inven";
}
}
}
if (from > to)
selecting = FALSE;
else {
if (scr_state == BLANK_SCR)
disp = ", * to list";
else
disp = "";
(void)sprintf(prt1,
"(%c-%c%s%s, space to break, ESC to exit) %s which one?",
from + 'a', to + 'a', disp, swap, prompt);
/* Abort everything. */
if (!get_com(prt1, &which)) {
selecting = FALSE;
which = ESCAPE;
}
/* Draw the screen and maybe exit to main prompt. */
else if (which == ' ' || which == '*') {
if (command == 't' || command == 'r')
inven_screen(EQUIP_SCR);
else if (command == 'w' && scr_state != INVEN_SCR)
inven_screen(WEAR_SCR);
else
inven_screen(INVEN_SCR);
if (which == ' ')
selecting = FALSE;
}
/* Swap screens (for drop) */
else if (which == '/' && swap[0]) {
if (command == 'd')
command = 'r';
else
command = 'd';
if (scr_state == EQUIP_SCR)
inven_screen(INVEN_SCR);
else if (scr_state == INVEN_SCR)
inven_screen(EQUIP_SCR);
} else if (((which < from + 'a') || (which > to + 'a'))
&& ((which < from + 'A') || (which > to + 'A')))
bell();
else { /* Found an item! */
if (isupper((int)which))
item = which - 'A';
else
item = which - 'a';
if (command == 'r' || command == 't') {
/* Get its place in the equipment list. */
tmp = item;
item = 21;
do {
item++;
if (inventory[item].tval != TV_NOTHING)
tmp--;
}
while (tmp >= 0);
if (isupper((int)which) && !verify(prompt, item))
item = (-1);
else if (TR_CURSED & inventory[item].flags) {
msg_print("Hmmm, it seems to be cursed.");
item = (-1);
} else if (command == 't' &&
!inven_check_num(&inventory[item])) {
if (cave[char_row][char_col].tptr != 0) {
msg_print("You can't carry it.");
item = (-1);
} else if (get_check("You can't carry it. Drop it?"))
command = 'r';
else
item = (-1);
}
if (item >= 0)
if (item == INVEN_LIGHT)
light_chg = TRUE;
if (command == 'r') {
inven_drop(item, TRUE);
/* As a safety measure, set the player's inven weight to 0,
* when the last object is dropped */
if (inven_ctr == 0 && equip_ctr == 0)
inven_weight = 0;
} else if (item >= 0) {
slot = inven_carry(&inventory[item]);
takeoff(item, slot);
}
check_strength();
free_turn_flag = FALSE;
if (command == 'r')
selecting = FALSE;
} else if (command == 'w') {
/* Wearing. Go to a bit of trouble over replacing existing equipment. */
if (isupper((int)which) && !verify(prompt, item))
item = (-1);
else
switch (inventory[item].tval) { /* Slot for equipment */
case TV_SLING_AMMO:
case TV_BOLT:
case TV_ARROW:
case TV_BOW:
case TV_HAFTED:
case TV_POLEARM:
case TV_SWORD:
case TV_DIGGING:
slot = INVEN_WIELD;
break;
case TV_LIGHT:
slot = INVEN_LIGHT;
break;
case TV_BOOTS:
slot = INVEN_FEET;
break;
case TV_GLOVES:
slot = INVEN_HANDS;
break;
case TV_CLOAK:
slot = INVEN_OUTER;
break;
case TV_HELM:
slot = INVEN_HEAD;
break;
case TV_SHIELD:
slot = INVEN_ARM;
break;
case TV_HARD_ARMOR:
case TV_SOFT_ARMOR:
slot = INVEN_BODY;
break;
case TV_AMULET:
slot = INVEN_NECK;
break;
case TV_RING:
if (inventory[INVEN_RIGHT].tval == TV_NOTHING)
slot = INVEN_RIGHT;
else if (inventory[INVEN_LEFT].tval == TV_NOTHING)
slot = INVEN_LEFT;
else {
slot = 0;
/*
* Rings. Give some choice over where they
* go.
*/
do {
if (!get_com(
"Put ring on which hand (l/r/L/R)?", &query)) {
item = (-1);
slot = (-1);
} else if (query == 'l')
slot = INVEN_LEFT;
else if (query == 'r')
slot = INVEN_RIGHT;
else {
if (query == 'L')
slot = INVEN_LEFT;
else if (query == 'R')
slot = INVEN_RIGHT;
else
bell();
if (slot && !verify("Replace", slot))
slot = 0;
}
}
while (slot == 0);
}
break;
default:
msg_print("IMPOSSIBLE: I don't see how you can use that.");
item = (-1);
break;
}
if (item >= 0 && inventory[slot].tval != TV_NOTHING) {
if (TR_CURSED & inventory[slot].flags) {
objdes(prt1, &inventory[slot], FALSE);
(void)sprintf(prt2, "The %s you are ", prt1);
if (slot == INVEN_WIELD) /* changed from
* INVEN_HEAD -CFT */
(void)strcat(prt2, "wielding ");
else
(void)strcat(prt2, "wearing ");
msg_print(strcat(prt2, "appears to be cursed."));
item = (-1);
} else if (inventory[item].subval == ITEM_GROUP_MIN &&
inventory[item].number > 1 &&
!inven_check_num(&inventory[slot])) {
/* this can happen if try to wield a torch, and have more than one in your inventory */
msg_print("You will have to drop something first.");
item = (-1);
}
}
if (item >= 0) {
/* OK. Wear it. */
free_turn_flag = FALSE;
if (slot == INVEN_LIGHT)
light_chg = TRUE;
/* first remove new item from inventory */
tmp_obj = inventory[item];
i_ptr = &tmp_obj;
wear_high--;
/* Fix for torches */
if (i_ptr->number > 1
&& i_ptr->subval <= ITEM_SINGLE_STACK_MAX) {
i_ptr->number = 1;
wear_high++;
}
inven_weight += i_ptr->weight * i_ptr->number;
inven_destroy(item); /* Subtracts weight */
/* second, add old item to inv and remove from equipment list, if necessary */
i_ptr = &inventory[slot];
if (i_ptr->tval != TV_NOTHING) {
tmp2 = inven_ctr;
tmp = inven_carry(i_ptr);
/* if item removed did not stack with anything in inventory, then increment wear_high */
if (inven_ctr != tmp2)
wear_high++;
takeoff(slot, tmp);
}
/* third, wear new item */
*i_ptr = tmp_obj;
equip_ctr++;
py_bonuses(i_ptr, 1);
if (slot == INVEN_WIELD)
string = "You are wielding";
else if (slot == INVEN_LIGHT)
string = "Your light source is";
else
string = "You are wearing";
objdes(prt2, i_ptr, TRUE);
/* Get the right equipment letter. */
tmp = INVEN_WIELD;
item = 0;
while (tmp != slot)
if (inventory[tmp++].tval != TV_NOTHING)
item++;
(void)sprintf(prt1, "%s %s. (%c)", string, prt2,
'a' + item);
msg_print(prt1);
/* check_str will clear the heavy flag if necessary */
check_strength();
if (i_ptr->flags & TR_CURSED) {
msg_print("Oops! It feels deathly cold!");
add_inscribe(i_ptr, ID_DAMD);
/* To force a cost of 0, even if unidentified. */
/* i_ptr->cost = (-1); Not... */
}
}
} else { /* command == 'd' */
if (inventory[item].number > 1) {
objdes(prt1, &inventory[item], TRUE);
(void)sprintf(prt2, "Drop all %s? [y/n]", prt1);
prt(prt2, 0, 0);
query = inkey();
if (query != 'y' && query != 'n') {
if (query != ESCAPE)
bell();
erase_line(MSG_LINE, 0);
item = (-1);
}
} else if (isupper((int)which) && !verify(prompt, item))
item = (-1);
else
query = 'y';
if (item >= 0) {
free_turn_flag = FALSE; /* Player turn */
inven_drop(item, query == 'y');
check_strength();
}
selecting = FALSE;
/* As a safety measure, set the player's inven weight to 0,
* when the last object is dropped. */
if (inven_ctr == 0 && equip_ctr == 0)
inven_weight = 0;
}
if (free_turn_flag == FALSE && scr_state == BLANK_SCR)
selecting = FALSE;
}
}
}
if (which == ESCAPE || scr_state == BLANK_SCR)
command = ESCAPE;
else if (!free_turn_flag) {
/* Save state for recovery if they want to call us again next turn. */
if (selecting)
doing_inven = command;
else
doing_inven = ' '; /* A dummy command to recover screen. */
/* flush last message before clearing screen_change and exiting */
msg_print(NULL);
screen_change = FALSE; /* This lets us know if the world changes */
command = ESCAPE;
} else {
/* Put an appropriate header. */
if (scr_state == INVEN_SCR) {
if (!show_weight_flag || inven_ctr == 0)
(void)sprintf(prt1,
"You are carrying %d.%d pounds. In your pack there is %s",
inven_weight / 10, inven_weight % 10,
(inven_ctr == 0 ? "nothing." : "-"));
else
(void)sprintf(prt1,
"You are carrying %d.%d pounds. Your capacity is %d.%d pounds. %s",
inven_weight / 10, inven_weight % 10,
weight_limit() / 10, weight_limit() % 10,
"In your pack is -");
prt(prt1, 0, 0);
} else if (scr_state == WEAR_SCR) {
if (wear_high < wear_low)
prt("You have nothing you could wield.", 0, 0);
else
prt("You could wield -", 0, 0);
} else if (scr_state == EQUIP_SCR) {
if (equip_ctr == 0)
prt("You are not using anything.", 0, 0);
else
prt("You are using -", 0, 0);
} else
prt("Allowed commands:", 0, 0);
erase_line(scr_base, scr_left);
put_buffer("e/i/t/w/x/d/?/ESC:", scr_base, 60);
command = inkey();
erase_line(scr_base, scr_left);
}
}
while (command != ESCAPE);
if (scr_state != BLANK_SCR)
restore_screen();
/* Update screen for changed light radius. -DGK */
/* Fix redisplay of lighting when in stores. -DGK */
if (light_chg && !in_store_flag) {
register int i, j;
int min_i, max_i, min_j, max_j;
/* replace a check for in_bounds2 every loop with 4 quick computations -CWS */
min_i = MY_MAX(0, (char_row - light_rad));
max_i = MY_MIN(cur_height, (char_row + light_rad));
min_j = MY_MAX(0, (char_col - light_rad));
max_j = MY_MIN(cur_width, (char_col + light_rad));
for (i = min_i; i <= max_i; i++)
for (j = min_j; j <= max_j; j++)
cave[i][j].tl = FALSE;
#ifdef TC_COLOR
textcolor(LIGHTGRAY);
#endif
tmp2 = light_rad;
print('@', char_row, char_col);
if (inventory[INVEN_LIGHT].tval == TV_LIGHT)
tmp = inventory[INVEN_LIGHT].subval;
else
tmp = 195;
light_rad = 1 + (tmp < 190) + (tmp == 4 || tmp == 6);
if (tmp2 < light_rad)
tmp2 = light_rad;
if (!py.flags.blind) {
min_i = MY_MAX(0, (char_row - light_rad));
max_i = MY_MIN(cur_height, (char_row + light_rad));
min_j = MY_MAX(0, (char_col - light_rad));
max_j = MY_MIN(cur_width, (char_col + light_rad));
for (i = min_i; i <= max_i; i++)
for (j = min_j; j <= max_j; j++)
if (los(char_row, char_col, i, j) &&
distance(char_row, char_col, i, j) <= light_rad)
cave[i][j].tl = TRUE;
}
min_i = MY_MAX(0, (char_row - tmp2));
max_i = MY_MIN(cur_height, (char_row + tmp2));
min_j = MY_MAX(0, (char_col - tmp2));
max_j = MY_MIN(cur_width, (char_col + tmp2));
for (i = min_i; i <= max_i; i++)
for (j = min_j; j <= max_j; j++)
lite_spot(i, j);
}
calc_bonuses();
/* If we ain't in a store, do the equippy chars -DGK*/
if (!in_store_flag)
prt_equippy_chars();
}
/* Get the ID of an item and return the CTR value of it -RAK- */
int
get_item(com_val, pmt, i, j, test)
int *com_val;
const char *pmt;
int i, j;
int (*test) ();
{
vtype out_val;
char which;
register int test_flag, item;
int full, i_scr, redraw;
int on_floor, ih;
cave_type *c_ptr;
/* check we're a) identifying and b) on the floor is an object
* and c) it is a object wich could be picked up
*/
c_ptr = &cave[char_row][char_col];
ih = t_list[c_ptr->tptr].tval;
on_floor = ( (strcmp("Item you wish identified?",pmt) == 0) &&
!( (c_ptr->tptr == 0) || ih == TV_NOTHING
|| ih > TV_MAX_PICK_UP) );
item = FALSE;
redraw = FALSE;
*com_val = 0;
i_scr = 1;
if (j > INVEN_WIELD) {
full = TRUE;
if (inven_ctr == 0) {
i_scr = 0;
j = equip_ctr - 1;
} else
j = inven_ctr - 1;
} else
full = FALSE;
if (inven_ctr > 0 || (full && equip_ctr > 0)) {
do {
if (redraw) {
if (i_scr > 0)
(void)show_inven(i, j, FALSE, 80, test);
else
(void)show_equip(FALSE, 80);
}
if (full)
(void)sprintf(out_val,
"(%s: %c-%c,%s%s / for %s, or ESC) %s",
(i_scr > 0 ? "Inven" : "Equip"), i + 'a', j + 'a',
(on_floor ? " - floor," : ""),
(redraw ? "" : " * to see,"),
(i_scr > 0 ? "Equip" : "Inven"), pmt);
else
(void)sprintf(out_val,
"(Items %c-%c,%s ESC to exit) %s", i + 'a', j + 'a',
(redraw ? "" : " * for inventory list,"), pmt);
test_flag = FALSE;
prt(out_val, 0, 0);
do {
which = inkey();
switch (which) {
case ESCAPE:
test_flag = TRUE;
free_turn_flag = TRUE;
i_scr = (-1);
break;
case '/':
if (full) {
if (i_scr > 0) {
if (equip_ctr == 0) {
prt("But you're not using anything -more-", 0, 0);
(void)inkey();
} else {
i_scr = 0;
test_flag = TRUE;
if (redraw) {
j = equip_ctr;
while (j < inven_ctr) {
j++;
erase_line(j, 0);
}
}
j = equip_ctr - 1;
}
prt(out_val, 0, 0);
} else {
if (inven_ctr == 0) {
prt("But you're not carrying anything -more-", 0, 0);
(void)inkey();
} else {
i_scr = 1;
test_flag = TRUE;
if (redraw) {
j = inven_ctr;
while (j < equip_ctr) {
j++;
erase_line(j, 0);
}
}
j = inven_ctr - 1;
}
}
}
break;
case '*':
if (!redraw) {
test_flag = TRUE;
save_screen();
redraw = TRUE;
}
break;
case '-':
/* not identified from INVEN or EQU but not aborted */
if (on_floor) {
item = FUZZY;
test_flag = TRUE;
i_scr = -1;
break;
}
default:
if (isupper((int)which))
*com_val = which - 'A';
else
*com_val = which - 'a';
if ((*com_val >= i) && (*com_val <= j)) {
if (i_scr == 0) {
i = 21;
j = *com_val;
do {
while (inventory[++i].tval == TV_NOTHING);
j--;
}
while (j >= 0);
*com_val = i;
}
if (isupper((int)which) && !verify("Try", *com_val)) {
test_flag = TRUE;
free_turn_flag = TRUE;
i_scr = (-1);
break;
}
test_flag = TRUE;
item = TRUE;
i_scr = (-1);
} else
bell();
break;
}
}
while (!test_flag);
}
while (i_scr >= 0);
if (redraw)
restore_screen();
erase_line(MSG_LINE, 0);
} else
prt("You are not carrying anything.", 0, 0);
return (item);
}
/* I may have written the town level code, but I'm not exactly */
/* proud of it. Adding the stores required some real slucky */
/* hooks which I have not had time to re-think. -RAK- */
/* Returns true if player has no light -RAK- */
int
no_light()
{
register cave_type *c_ptr;
c_ptr = &cave[char_row][char_col];
if (!c_ptr->tl && !c_ptr->pl)
return TRUE;
return FALSE;
}
/* map rogue_like direction commands into numbers */
static char
map_roguedir(my_comval)
register int my_comval;
{
char comval = (char)my_comval;
switch (comval) {
case 'h':
comval = '4';
break;
case 'y':
comval = '7';
break;
case 'k':
comval = '8';
break;
case 'u':
comval = '9';
break;
case 'l':
comval = '6';
break;
case 'n':
comval = '3';
break;
case 'j':
comval = '2';
break;
case 'b':
comval = '1';
break;
case '.':
comval = '5';
break;
}
return (comval);
}
/* Prompts for a direction -RAK- */
/* Direction memory added, for repeated commands. -CJS */
int
get_dir(prompt, dir)
const char *prompt;
int *dir;
{
char command;
int save;
static char prev_dir; /* Direction memory. -CJS- */
if (default_dir) { /* used in counted commands. -CJS- */
*dir = prev_dir;
return TRUE;
}
#ifdef TARGET
/* This targetting code stolen from Morgul -CFT */
/* Aggle. Gotta be target mode and either (valid monster and line of sight*/
/* to monster) or (not valid monster and line of sight to position). CDW */
/* Also, for monster targetting, monster must be lit! Otherwise player can
"lock phasers" on an invis monster while a potion of see inv lasts,
and then continue to hit it when the see inv goes away. Also,
targetting mode shouldn't help the player shoot a monster in a
dark room. If he can't see it, he shouldn't be able to aim... -CFT */
if ((target_mode)&&
(((target_mon<MAX_MALLOC)&& m_list[target_mon].ml &&
(los(char_row,char_col,m_list[target_mon].fy,m_list[target_mon].fx))||
((target_mon>=MAX_MALLOC) &&
(los(char_row,char_col,target_row,target_col)))))) {
/* It don't get no better than this */
*dir=0;
return TRUE;
}
else {
#endif
if (prompt == NULL)
prompt = "Which direction?";
for (;;) {
save = command_count; /* Don't end a counted command. -CJS- */
#ifdef MAC
if (!get_comdir(prompt, &command))
#else
if (!get_com(prompt, &command))
#endif
{
free_turn_flag = TRUE;
return FALSE;
}
command_count = save;
if (rogue_like_commands)
command = map_roguedir(command);
if (command >= '1' && command <= '9' && command != '5') {
prev_dir = command - '0';
*dir = prev_dir;
return TRUE;
}
bell();
}
#ifdef TARGET
}
#endif
}
/*
* Similar to get_dir, except that no memory exists, and it is -CJS-
* allowed to enter the null direction.
*/
int
get_alldir(prompt, dir)
const char *prompt;
int *dir;
{
char command;
for (;;) {
#ifdef MAC
if (!get_comdir(prompt, &command))
#else
if (!get_com(prompt, &command))
#endif
{
free_turn_flag = TRUE;
return FALSE;
}
if (rogue_like_commands)
command = map_roguedir(command);
if (command >= '1' && command <= '9') {
*dir = command - '0';
return TRUE;
}
bell();
}
}
/* Moves creature record from one space to another -RAK- */
void
move_rec(y1, x1, y2, x2)
register int y1, x1, y2, x2;
{
int tmp;
/* this always works correctly, even if y1==y2 and x1==x2 */
tmp = cave[y1][x1].cptr;
cave[y1][x1].cptr = 0;
cave[y2][x2].cptr = tmp;
}
static void
flood_light(y,x)
int y,x;
{
register cave_type *c_ptr;
register int temp;
c_ptr = &cave[y][x];
if (c_ptr->lr) {
temp=c_ptr->tl;
c_ptr->tl = TRUE;
if (c_ptr->fval<MIN_CLOSED_SPACE && temp==FALSE) {
flood_light(y+1,x);
flood_light(y-1,x);
flood_light(y,x+1);
flood_light(y,x-1);
flood_light(y+1,x+1);
flood_light(y-1,x-1);
flood_light(y-1,x+1);
flood_light(y+1,x-1);
}
}
}
static void flood_permanent(y,x)
int y,x;
{
register cave_type *c_ptr;
c_ptr = &cave[y][x];
if (c_ptr->tl) {
c_ptr->tl = FALSE;
c_ptr->pl = TRUE;
if (c_ptr->fval==NT_DARK_FLOOR)
c_ptr->fval=NT_LIGHT_FLOOR;
else if (c_ptr->fval==DARK_FLOOR)
c_ptr->fval=LIGHT_FLOOR;
#ifdef MSDOS
lite_spot(y,x); /* this does all that; plus color-safe -CFT */
#else
if ((y-panel_row_prt)<23 && (y-panel_row_prt)>0 &&
(x-panel_col_prt)>12 && (x-panel_col_prt)<80)
print(loc_symbol(y, x), y, x);
#endif
if (c_ptr->fval<MIN_CLOSED_SPACE) {
flood_permanent(y+1,x);
flood_permanent(y-1,x);
flood_permanent(y,x+1);
flood_permanent(y,x-1);
flood_permanent(y+1,x+1);
flood_permanent(y-1,x-1);
flood_permanent(y-1,x+1);
flood_permanent(y+1,x-1);
}
}
}
static void
flood_permanent_dark(y,x)
int y,x;
{
register cave_type *c_ptr;
c_ptr = &cave[y][x];
if (c_ptr->tl) {
c_ptr->tl = FALSE;
if (c_ptr->fval==NT_LIGHT_FLOOR)
c_ptr->fval=NT_DARK_FLOOR;
else if (c_ptr->fval==LIGHT_FLOOR)
c_ptr->fval=DARK_FLOOR;
#ifdef MSDOS
if (panel_contains(y,x)) {
if (c_ptr->fval < MIN_CLOSED_SPACE){
c_ptr->pl = FALSE;
flood_permanent_dark(y+1,x);
flood_permanent_dark(y-1,x);
flood_permanent_dark(y,x+1);
flood_permanent_dark(y,x-1);
flood_permanent_dark(y+1,x+1);
flood_permanent_dark(y-1,x-1);
flood_permanent_dark(y-1,x+1);
flood_permanent_dark(y+1,x-1);
}
lite_spot(y,x);
}
#else
if ((y-panel_row_prt)<23 && (y-panel_row_prt)>0 &&
(x-panel_col_prt)>12 && (x-panel_col_prt)<80)
if (c_ptr->fval<MIN_CLOSED_SPACE) {
c_ptr->pl = FALSE;
flood_permanent_dark(y+1,x);
flood_permanent_dark(y-1,x);
flood_permanent_dark(y,x+1);
flood_permanent_dark(y,x-1);
flood_permanent_dark(y+1,x+1);
flood_permanent_dark(y-1,x-1);
flood_permanent_dark(y-1,x+1);
flood_permanent_dark(y+1,x-1);
}
print(loc_symbol(y, x), y, x);
#endif
}
}
void
light_room(y, x)
int y, x;
{
register cave_type *c_ptr;
register monster_type *m_ptr;
c_ptr = &cave[y][x];
if (!c_ptr->pl && c_ptr->lr) {
c_ptr->pl = TRUE;
m_ptr = &m_list[c_ptr->cptr];
/* Monsters that are intelligent wake up all the time; non-MINDLESS monsters wake
* up 1/3 the time, and MINDLESS monsters wake up 1/10 the time -CWS
*/
if ((c_list[m_ptr->mptr].cdefense & INTELLIGENT) ||
(!(c_list[m_ptr->mptr].cdefense & MINDLESS) && (randint(3) == 1)) ||
(randint(10) == 1))
m_ptr->csleep = 0;
if (c_ptr->fval == NT_DARK_FLOOR)
c_ptr->fval = NT_LIGHT_FLOOR;
else if (c_ptr->fval == DARK_FLOOR)
c_ptr->fval = LIGHT_FLOOR;
#ifdef MSDOS
lite_spot(y, x); /* this does all that; plus color-safe -CFT */
#else
if ((y - panel_row_prt) < 23 && (y - panel_row_prt) > 0 &&
(x - panel_col_prt) > 12 && (x - panel_col_prt) < 80)
print(loc_symbol(y, x), y, x);
#endif
if (c_ptr->fval < MIN_CLOSED_SPACE) {
c_ptr = &cave[y + 1][x];
if ((!c_ptr->pl) && (c_ptr->lr))
light_room(y + 1, x);
c_ptr = &cave[y - 1][x];
if ((!c_ptr->pl) && (c_ptr->lr))
light_room(y - 1, x);
c_ptr = &cave[y][x + 1];
if ((!c_ptr->pl) && (c_ptr->lr))
light_room(y, x + 1);
c_ptr = &cave[y][x - 1];
if ((!c_ptr->pl) && (c_ptr->lr))
light_room(y, x - 1);
c_ptr = &cave[y + 1][x + 1];
if ((!c_ptr->pl) && (c_ptr->lr))
light_room(y + 1, x + 1);
c_ptr = &cave[y - 1][x - 1];
if ((!c_ptr->pl) && (c_ptr->lr))
light_room(y - 1, x - 1);
c_ptr = &cave[y - 1][x + 1];
if ((!c_ptr->pl) && (c_ptr->lr))
light_room(y - 1, x + 1);
c_ptr = &cave[y + 1][x - 1];
if ((!c_ptr->pl) && (c_ptr->lr))
light_room(y + 1, x - 1);
}
}
}
void
darken_room(y, x)
int y, x;
{
register cave_type *c_ptr;
c_ptr = &cave[y][x];
if (c_ptr->pl && c_ptr->lr) {
c_ptr->tl = FALSE;
if (c_ptr->fval == NT_LIGHT_FLOOR)
c_ptr->fval = NT_DARK_FLOOR;
else if (c_ptr->fval == LIGHT_FLOOR)
c_ptr->fval = DARK_FLOOR;
#ifdef MSDOS
if (panel_contains(y, x))
if (c_ptr->fval < MIN_CLOSED_SPACE) {
#else
if ((y - panel_row_prt) < 23 && (y - panel_row_prt) > 0 &&
(x - panel_col_prt) > 12 && (x - panel_col_prt) < 80)
if (c_ptr->fval < MIN_CLOSED_SPACE) {
#endif
c_ptr->pl = FALSE;
darken_room(y + 1, x);
darken_room(y - 1, x);
darken_room(y, x + 1);
darken_room(y, x - 1);
darken_room(y + 1, x + 1);
darken_room(y - 1, x - 1);
darken_room(y - 1, x + 1);
darken_room(y + 1, x - 1);
}
print(loc_symbol(y, x), y, x);
}
}
/* Lights up given location -RAK- */
void
lite_spot(y, x)
register int y, x;
{
if (panel_contains(y, x))
print(loc_symbol(y, x), y, x);
}
/* Normal movement */
/* When FIND_FLAG, light only permanent features */
static void
sub1_move_light(y1, x1, y2, x2)
register int x1, x2;
int y1, y2;
{
register int i, j;
register cave_type *c_ptr;
int tval, top, left, bottom, right;
int min_i, max_i, min_j, max_j;
if (light_flag) {
darken_player(y1, x1);
if (find_flag && !find_prself)
light_flag = FALSE;
} else if (!find_flag || find_prself)
light_flag = TRUE;
/* replace a check for in_bounds2 every loop with 4 quick computations -CWS */
min_i = MY_MAX(0, (y2 - light_rad));
max_i = MY_MIN(cur_height, (y2 + light_rad));
min_j = MY_MAX(0, (x2 - light_rad));
max_j = MY_MIN(cur_width, (x2 + light_rad));
for (i = min_i; i <= max_i; i++)
for (j = min_j; j <= max_j; j++)
if (los(y2, x2, i, j) && distance(i, j, y2, x2) <= light_rad) {
c_ptr = &cave[i][j];
/* only light up if normal movement */
if (light_flag)
c_ptr->tl = TRUE;
if (c_ptr->fval >= MIN_CAVE_WALL)
c_ptr->pl = TRUE;
else if (!c_ptr->fm && c_ptr->tptr != 0) {
tval = t_list[c_ptr->tptr].tval;
if ((tval >= TV_MIN_VISIBLE) && (tval <= TV_MAX_VISIBLE))
c_ptr->fm = TRUE;
}
}
/* From uppermost to bottom most lines player was on. */
if (y1 < y2) {
top = y1 - light_rad;
bottom = y2 + light_rad;
} else {
top = y2 - light_rad;
bottom = y1 + light_rad;
}
if (x1 < x2) {
left = x1 - light_rad;
right = x2 + light_rad;
} else {
left = x2 - light_rad;
right = x1 + light_rad;
}
for (i = top; i <= bottom; i++)
for (j = left; j <= right; j++) /* Leftmost to rightmost do */
lite_spot(i, j); /* this does that, plus panel check +
* color safe */
}
/* When blinded, move only the player symbol. */
/* With no light, movement becomes involved. */
static void
sub3_move_light(y1, x1, y2, x2)
register int y1, x1;
int y2, x2;
{
if (light_flag) {
darken_player(y1, x1);
light_flag = FALSE;
} else if (!find_flag || find_prself) /* um55 change -CFT */
lite_spot(y1, x1);
#ifdef TC_COLOR
if (!no_color_flag)
textcolor(LIGHTGRAY);
#endif
if (!find_flag || find_prself)
print('@', y2, x2);
}
void
darken_player(y1, x1)
int y1, x1;
{
int min_i, max_i, min_j, max_j, rad, i, j;
rad = MY_MAX(light_rad, old_rad);
/* replace a check for in_bounds2 every loop with 4 quick computations -CWS */
min_i = MY_MAX(0, (y1 - rad));
max_i = MY_MIN(cur_height, (y1 + rad));
min_j = MY_MAX(0, (x1 - rad));
max_j = MY_MIN(cur_width, (x1 + rad));
for (i = min_i; i <= max_i; i++)
for (j = min_j; j <= max_j; j++) {
cave[i][j].tl = FALSE; /* Turn off light */
lite_spot(i, j);
}
}
/* Package for moving the character's light about the screen */
/* Four cases : Normal, Finding, Blind, and Nolight -RAK- */
void
move_light(y1, x1, y2, x2)
int y1, x1, y2, x2;
{
if (py.flags.blind > 0 || !player_light)
sub3_move_light(y1, x1, y2, x2);
else
sub1_move_light(y1, x1, y2, x2);
}
/*
* Something happens to disturb the player. -CJS- The first arg
* indicates a major disturbance, which affects search. The second arg
* indicates a light change.
*/
void
disturb(s, l)
int s, l;
{
command_count = 0;
if (s && (py.flags.status & PY_SEARCH))
search_off();
if (py.flags.rest != 0)
rest_off();
if (l || find_flag) {
find_flag = FALSE;
check_view();
}
flush();
}
/* Search Mode enhancement -RAK- */
void
search_on()
{
change_speed(1);
py.flags.status |= PY_SEARCH;
prt_state();
prt_speed();
py.flags.food_digested++;
}
void
search_off()
{
check_view();
change_speed(-1);
py.flags.status &= ~PY_SEARCH;
prt_state();
prt_speed();
py.flags.food_digested--;
}
/* Resting allows a player to safely restore his hp -RAK- */
void
rest()
{
int rest_num;
vtype rest_str;
if (command_count > 0) {
rest_num = command_count;
command_count = 0;
} else {
char ch;
prt("Rest for how long? ('*' for HP/mana; '&' as needed) : ", 0, 0);
rest_num = 0;
if (get_string(rest_str, 0, 54, 5)) {
if (sscanf(rest_str, "%c", &ch) == 1)
if (ch == '*')
rest_num = (-1);
else if (ch == '&')
rest_num = (-2);
else {
if (atoi(rest_str) > 30000)
rest_num = 30000;
else
rest_num = atoi(rest_str);
}
}
}
if (rest_num != 0) {
if (py.flags.status & PY_SEARCH)
search_off();
py.flags.rest = rest_num;
py.flags.status |= PY_REST;
prt_state();
py.flags.food_digested--;
prt("Press any key to stop resting...", 0, 0);
put_qio();
} else {
erase_line(MSG_LINE, 0);
free_turn_flag = TRUE;
}
}
void
rest_off()
{
py.flags.rest = 0;
py.flags.status &= ~PY_REST;
prt_state();
msg_print(NULL); /* flush last message, or delete "press
* any key" message */
py.flags.food_digested++;
}
/* Attacker's level and plusses, defender's AC -RAK- */
int
test_hit(bth, level, pth, ac, attack_type)
int bth, level, pth, ac, attack_type;
{
register int i, die;
disturb(1, 0);
i = bth + pth * BTH_PLUS_ADJ
+ (level * class_level_adj[py.misc.pclass][attack_type]);
/* pth could be less than 0 if player wielding weapon too heavy for him */
/* always miss 1 out of 20, always hit 1 out of 20 */
die = randint(20);
if ((die != 1) && ((die == 20)
|| ((i > 0) && (randint(i) > ((3 * ac) / 4)))))
return TRUE;
else
return FALSE;
}
/* Decreases players hit points and sets death flag if necessary */
/* -RAK- */
void
take_hit(damage, hit_from)
int damage;
const char *hit_from;
{
if (py.flags.invuln > 0 && damage < 9000)
damage = 0;
py.misc.chp -= damage;
if (py.misc.chp < 0) {
if ((wizard) && !(get_Yn("Die?"))) {
py.misc.chp=py.misc.mhp;
death=FALSE;
prt_chp();
msg_print("OK, so you don't die.");
} else {
if (!death) {
death = TRUE;
(void)strcpy(died_from, hit_from);
total_winner = FALSE;
}
new_level_flag = TRUE;
}
} else
prt_chp();
if (py.misc.chp <= py.misc.mhp * hitpoint_warn / 10) {
msg_print("*** LOW HITPOINT WARNING! ***");
msg_print(NULL); /* make sure they see it -CWS */
}
}
/* Change a trap from invisible to visible -RAK- */
/* Note: Secret doors are handled here */
void
change_trap(y, x)
register int y, x;
{
register cave_type *c_ptr;
register inven_type *t_ptr;
c_ptr = &cave[y][x];
t_ptr = &t_list[c_ptr->tptr];
if (t_ptr->tval == TV_INVIS_TRAP) {
t_ptr->tval = TV_VIS_TRAP;
lite_spot(y, x);
} else if (t_ptr->tval == TV_SECRET_DOOR) {
/* change secret door to closed door */
t_ptr->index = OBJ_CLOSED_DOOR;
t_ptr->tval = object_list[OBJ_CLOSED_DOOR].tval;
t_ptr->tchar = object_list[OBJ_CLOSED_DOOR].tchar;
lite_spot(y, x);
}
}
/* Searches for hidden things. -RAK- */
void
search(y, x, chance)
int y, x, chance;
{
register int i, j;
register cave_type *c_ptr;
register inven_type *t_ptr;
register struct flags *p_ptr;
bigvtype tmp_str, tmp_str2;
p_ptr = &py.flags;
if (p_ptr->confused > 0)
chance = chance / 10;
if ((p_ptr->blind > 0) || no_light())
chance = chance / 10;
if (p_ptr->image > 0)
chance = chance / 10;
for (i = (y - 1); i <= (y + 1); i++)
for (j = (x - 1); j <= (x + 1); j++)
if (randint(100) < chance) { /* always in_bounds here */
c_ptr = &cave[i][j];
/* Search for hidden objects */
if (c_ptr->tptr != 0) {
t_ptr = &t_list[c_ptr->tptr];
/* Trap on floor? */
if (t_ptr->tval == TV_INVIS_TRAP) {
objdes(tmp_str2, t_ptr, TRUE);
(void)sprintf(tmp_str, "You have found %s.", tmp_str2);
msg_print(tmp_str);
change_trap(i, j);
end_find();
}
/* Secret door? */
else if (t_ptr->tval == TV_SECRET_DOOR) {
msg_print("You have found a secret door.");
change_trap(i, j);
end_find();
}
/* Chest is trapped? */
else if (t_ptr->tval == TV_CHEST) {
/* mask out the treasure bits */
if ((t_ptr->flags & CH_TRAPPED) > 1)
if (!known2_p(t_ptr)) {
known2(t_ptr);
msg_print("You have discovered a trap on the chest!");
} else
msg_print("The chest is trapped!");
}
}
}
}
/* The running algorithm: -CJS-
Overview: You keep moving until something interesting happens.
If you are in an enclosed space, you follow corners. This is
the usual corridor scheme. If you are in an open space, you go
straight, but stop before entering enclosed space. This is
analogous to reaching doorways. If you have enclosed space on
one side only (that is, running along side a wall) stop if
your wall opens out, or your open space closes in. Either case
corresponds to a doorway.
What happens depends on what you can really SEE. (i.e. if you
have no light, then running along a dark corridor is JUST like
running in a dark room.) The algorithm works equally well in
corridors, rooms, mine tailings, earthquake rubble, etc, etc.
These conditions are kept in static memory:
find_openarea You are in the open on at least one
side.
find_breakleft You have a wall on the left, and will
stop if it opens
find_breakright You have a wall on the right, and will
stop if it opens
To initialize these conditions is the task of find_init. If
moving from the square marked @ to the square marked . (in the
two diagrams below), then two adjacent sqares on the left and
the right (L and R) are considered. If either one is seen to
be closed, then that side is considered to be closed. If both
sides are closed, then it is an enclosed (corridor) run.
LL L
@. L.R
RR @R
Looking at more than just the immediate squares is
significant. Consider the following case. A run along the
corridor will stop just before entering the center point,
because a choice is clearly established. Running in any of
three available directions will be defined as a corridor run.
Note that a minor hack is inserted to make the angled corridor
entry (with one side blocked near and the other side blocked
further away from the runner) work correctly. The runner moves
diagonally, but then saves the previous direction as being
straight into the gap. Otherwise, the tail end of the other
entry would be perceived as an alternative on the next move.
#.#
##.##
.@...
##.##
#.#
Likewise, a run along a wall, and then into a doorway (two
runs) will work correctly. A single run rightwards from @ will
stop at 1. Another run right and down will enter the corridor
and make the corner, stopping at the 2.
#@ 1
########### ######
2 #
#############
#
After any move, the function area_affect is called to
determine the new surroundings, and the direction of
subsequent moves. It takes a location (at which the runner has
just arrived) and the previous direction (from which the
runner is considered to have come). Moving one square in some
direction places you adjacent to three or five new squares
(for straight and diagonal moves) to which you were not
previously adjacent.
...! ... EG Moving from 1 to 2.
.12! .1.! . means previously adjacent
...! ..2! ! means newly adjacent
!!!
You STOP if you can't even make the move in the chosen
direction. You STOP if any of the new squares are interesting
in any way: usually containing monsters or treasure. You STOP
if any of the newly adjacent squares seem to be open, and you
are also looking for a break on that side. (i.e. find_openarea
AND find_break) You STOP if any of the newly adjacent squares
do NOT seem to be open and you are in an open area, and that
side was previously entirely open.
Corners: If you are not in the open (i.e. you are in a
corridor) and there is only one way to go in the new squares,
then turn in that direction. If there are more than two new
ways to go, STOP. If there are two ways to go, and those ways
are separated by a square which does not seem to be open, then
STOP.
Otherwise, we have a potential corner. There are two new open
squares, which are also adjacent. One of the new squares is
diagonally located, the other is straight on (as in the
diagram). We consider two more squares further out (marked
below as ?).
.X
@.?
#?
If they are both seen to be closed, then it is seen that no
benefit is gained from moving straight. It is a known corner.
To cut the corner, go diagonally, otherwise go straight, but
pretend you stepped diagonally into that next location for a
full view next time. Conversely, if one of the ? squares is
not seen to be closed, then there is a potential choice. We check
to see whether it is a potential corner or an intersection/room entrance.
If the square two spaces straight ahead, and the space marked with 'X'
are both blank, then it is a potential corner and enter if find_examine
is set, otherwise must stop because it is not a corner. */
/*
* The cycle lists the directions in anticlockwise order, for -CJS- over
* two complete cycles. The chome array maps a direction on to its position
* in the cycle.
*/
static int cycle[] = {1, 2, 3, 6, 9, 8, 7, 4, 1, 2, 3, 6, 9, 8, 7, 4, 1};
static int chome[] = {-1, 8, 9, 10, 7, -1, 11, 6, 5, 4};
static int find_openarea, find_breakright, find_breakleft, find_prevdir;
static int find_direction;/* Keep a record of which way we are going. */
void
find_init(dir)
int dir;
{
int row, col, deepleft, deepright;
register int i, shortleft, shortright;
darken_player(char_row, char_col);
old_rad = light_rad;
if (light_rad >= 0)
light_rad = 1;
row = char_row;
col = char_col;
if (!mmove(dir, &row, &col))
find_flag = FALSE;
else {
find_direction = dir;
find_flag = 1;
find_breakright = find_breakleft = FALSE;
find_prevdir = dir;
if (py.flags.blind < 1) {
i = chome[dir];
deepleft = deepright = FALSE;
shortright = shortleft = FALSE;
if (see_wall(cycle[i + 1], char_row, char_col)) {
find_breakleft = TRUE;
shortleft = TRUE;
} else if (see_wall(cycle[i + 1], row, col)) {
find_breakleft = TRUE;
deepleft = TRUE;
}
if (see_wall(cycle[i - 1], char_row, char_col)) {
find_breakright = TRUE;
shortright = TRUE;
} else if (see_wall(cycle[i - 1], row, col)) {
find_breakright = TRUE;
deepright = TRUE;
}
if (find_breakleft && find_breakright) {
find_openarea = FALSE;
if (dir & 1) { /* a hack to allow angled corridor entry */
if (deepleft && !deepright)
find_prevdir = cycle[i - 1];
else if (deepright && !deepleft)
find_prevdir = cycle[i + 1];
}
/* else if there is a wall two spaces ahead and seem to be in a
* corridor, then force a turn into the side corridor, must be
* moving straight into a corridor here
*/
else if (see_wall(cycle[i], row, col)) {
if (shortleft && !shortright)
find_prevdir = cycle[i - 2];
else if (shortright && !shortleft)
find_prevdir = cycle[i + 2];
}
} else
find_openarea = TRUE;
}
}
/*
* We must erase the player symbol '@' here, because sub3_move_light() does
* not erase the previous location of the player when in find mode and when
* find_prself is FALSE. The player symbol is not draw at all in this case
* while moving, so the only problem is on the first turn of find mode, when
* the initial position of the character must be erased. Hence we must do the
* erasure here.
*/
if (!light_flag && !find_prself)
#ifdef TC_COLOR
lite_spot(char_row, char_col);
#else
print(loc_symbol(char_row, char_col), char_row, char_col);
#endif
move_char(dir, TRUE);
if (find_flag == FALSE)
command_count = 0;
}
void
find_run()
{
/* prevent infinite loops in find mode, will stop after moving 100 times */
if (find_flag++ > 100) {
msg_print("You stop running to catch your breath.");
end_find();
} else
move_char(find_direction, TRUE);
}
/* Switch off the run flag - and get the light correct. -CJS- */
void
end_find()
{
if (find_flag) {
find_flag = FALSE;
light_rad = old_rad;
move_light(char_row, char_col, char_row, char_col);
}
}
/* Do we see a wall? Used in running. -CJS- */
static int
see_wall(dir, y, x)
int dir, y, x;
{
char c;
if (!mmove(dir, &y, &x)) /* check to see if movement there possible */
return TRUE;
#ifdef MSDOS
else if ((c = loc_symbol(y, x)) == wallsym || c == '%')
#else
#ifdef ATARIST_MWC
else if ((c = loc_symbol(y, x)) == (unsigned char)240 || c == '%')
#else
else if ((c = loc_symbol(y, x)) == '#' || c == '%')
#endif
#endif
return TRUE;
else
return FALSE;
}
/* Do we see anything? Used in running. -CJS- */
static int
see_nothing(dir, y, x)
int dir, y, x;
{
if (!mmove(dir, &y, &x)) /* check to see if movement there possible */
return FALSE;
else if (loc_symbol(y, x) == ' ')
return TRUE;
else
return FALSE;
}
/* Determine the next direction for a run, or if we should stop. -CJS- */
void
area_affect(dir, y, x)
int dir, y, x;
{
int newdir = 0, t, inv, check_dir = 0, row, col;
register int i, max, option, option2;
register cave_type *c_ptr;
if (py.flags.blind < 1) {
option = 0;
option2 = 0;
dir = find_prevdir;
max = (dir & 1) + 1;
/* Look at every newly adjacent square. */
for (i = -max; i <= max; i++) {
newdir = cycle[chome[dir] + i];
row = y;
col = x;
if (mmove(newdir, &row, &col)) {
/* Objects player can see (Including doors?) cause a stop. */
c_ptr = &cave[row][col];
if (player_light || c_ptr->tl || c_ptr->pl || c_ptr->fm) {
if (c_ptr->tptr != 0) {
t = t_list[c_ptr->tptr].tval;
if (t != TV_INVIS_TRAP && t != TV_SECRET_DOOR
&& (t != TV_OPEN_DOOR || !find_ignore_doors)) {
end_find();
return;
}
}
/* Also Creatures */
/* the monster should be visible since update_mon() checks
* for the special case of being in find mode
*/
if (c_ptr->cptr > 1 && m_list[c_ptr->cptr].ml) {
end_find();
return;
}
inv = FALSE;
} else
inv = TRUE; /* Square unseen. Treat as open. */
if (c_ptr->fval <= MAX_OPEN_SPACE || inv) {
if (find_openarea) {
if (i < 0) {
if (find_breakright) {
end_find();
return;
}
} else if (i > 0) {
if (find_breakleft) {
end_find();
return;
}
}
} else if (option == 0)
option = newdir; /* The first new direction. */
else if (option2 != 0) {
end_find(); /* Three new directions. STOP. */
return;
} else if (option != cycle[chome[dir] + i - 1]) {
end_find();/* If not adjacent to prev, STOP */
return;
} else {
/* Two adjacent choices. Make option2 the diagonal, and
* remember the other diagonal adjacent to the first
* option.
*/
if ((newdir & 1) == 1) {
check_dir = cycle[chome[dir] + i - 2];
option2 = newdir;
} else {
check_dir = cycle[chome[dir] + i + 1];
option2 = option;
option = newdir;
}
}
} else if (find_openarea) {
/* We see an obstacle. In open area, STOP if on a side previously open. */
if (i < 0) {
if (find_breakleft) {
end_find();
return;
}
find_breakright = TRUE;
} else if (i > 0) {
if (find_breakright) {
end_find();
return;
}
find_breakleft = TRUE;
}
}
}
}
if (find_openarea == FALSE) { /* choose a direction. */
if (option2 == 0 || (find_examine && !find_cut)) {
/* There is only one option, or if two, then we always examine
* potential corners and never cut known corners, so you step
* into the straight option.
*/
if (option != 0)
find_direction = option;
if (option2 == 0)
find_prevdir = option;
else
find_prevdir = option2;
} else {
/* Two options! */
row = y;
col = x;
(void)mmove(option, &row, &col);
if (!see_wall(option, row, col)
|| !see_wall(check_dir, row, col)) {
/*
* Don't see that it is closed off. This could be a
* potential corner or an intersection.
*/
if (find_examine && see_nothing(option, row, col)
&& see_nothing(option2, row, col))
/*
* Can not see anything ahead and in the direction we are
* turning, assume that it is a potential corner.
*/
{
find_direction = option;
find_prevdir = option2;
} else
/* STOP: we are next to an intersection or a room */
end_find();
} else if (find_cut) {
/* This corner is seen to be enclosed; we cut the corner. */
find_direction = option2;
find_prevdir = option2;
} else {
/*
* This corner is seen to be enclosed, and we deliberately go
* the long way.
*/
find_direction = option;
find_prevdir = option2;
}
}
}
}
}
/* AC gets worse -RAK- */
/* Note: This routine affects magical AC bonuses so that stores */
/* can detect the damage. */
int
minus_ac(typ_dam)
int32u typ_dam;
{
register int i, j;
int tmp[6], minus, do_damage;
register inven_type *i_ptr;
bigvtype out_val, tmp_str;
i = 0;
if (inventory[INVEN_BODY].tval != TV_NOTHING) {
tmp[i] = INVEN_BODY;
i++;
}
if (inventory[INVEN_ARM].tval != TV_NOTHING) {
tmp[i] = INVEN_ARM;
i++;
}
if (inventory[INVEN_OUTER].tval != TV_NOTHING) {
tmp[i] = INVEN_OUTER;
i++;
}
if (inventory[INVEN_HANDS].tval != TV_NOTHING) {
tmp[i] = INVEN_HANDS;
i++;
}
if (inventory[INVEN_HEAD].tval != TV_NOTHING) {
tmp[i] = INVEN_HEAD;
i++;
}
/* also affect boots */
if (inventory[INVEN_FEET].tval != TV_NOTHING) {
tmp[i] = INVEN_FEET;
i++;
}
minus = FALSE;
if (i > 0) {
j = tmp[randint(i) - 1];
i_ptr = &inventory[j];
switch (typ_dam) {
case TR_RES_ACID:
if ((i_ptr->flags & TR_RES_ACID) || (i_ptr->flags2 & TR_IM_ACID) ||
((i_ptr->flags2 & TR_ARTIFACT) && (randint(5)>2)))
do_damage = FALSE;
else
do_damage = TRUE;
break;
default: /* unknown damage type... */
do_damage = FALSE;
}
if (do_damage == FALSE) {
objdes(tmp_str, &inventory[j], FALSE);
(void)sprintf(out_val, "Your %s resists damage!", tmp_str);
msg_print(out_val);
minus = FALSE;
} else if ((i_ptr->ac + i_ptr->toac) > 0) {
objdes(tmp_str, &inventory[j], FALSE);
(void)sprintf(out_val, "Your %s is damaged!", tmp_str);
msg_print(out_val);
i_ptr->toac--;
calc_bonuses();
minus = TRUE;
}
}
return (minus);
}
/* Corrode the unsuspecting person's armor -RAK- */
void
corrode_gas(kb_str)
const char *kb_str;
{
if (!py.flags.acid_im)
if (!minus_ac((int32u) TR_RES_ACID))
take_hit(randint(8), kb_str);
inven_damage(set_corrodes, 5);
}
/* Poison gas the idiot. -RAK- */
void
poison_gas(dam, kb_str)
int dam;
const char *kb_str;
{
if (py.flags.resist_poison > 0)
dam = 2 * dam / 3;
if (py.flags.poison_resist)
dam = (dam * 3) / 5;
if (py.flags.poison_im)
dam = 1;
take_hit(dam, kb_str);
if (!(py.flags.poison_resist || py.flags.resist_poison
|| py.flags.poison_im))
py.flags.poisoned += 12 + randint(dam);
}
/* Burn the fool up. -RAK- */
void
fire_dam(dam, kb_str)
int dam;
const char *kb_str;
{
if (py.flags.fire_resist)
dam = dam / 3;
if (py.flags.resist_heat > 0)
dam = dam / 3;
if (py.flags.fire_im)
dam = 1;
take_hit(dam, kb_str);
inven_damage(set_flammable, 3);
}
/* Freeze him to death. -RAK- */
void
cold_dam(dam, kb_str)
int dam;
const char *kb_str;
{
if (py.flags.cold_resist)
dam = dam / 3;
if (py.flags.resist_cold > 0)
dam = dam / 3;
if (py.flags.cold_im)
dam = 1;
take_hit(dam, kb_str);
inven_damage(set_frost_destroy, 5);
}
/* Lightning bolt the sucker away. -RAK- */
void
light_dam(dam, kb_str)
int dam;
const char *kb_str;
{
if (py.flags.resist_light)
dam = dam / 3;
if (py.flags.lght_resist)
dam = dam / 3;
if (py.flags.light_im)
dam = 1;
take_hit(dam, kb_str);
inven_damage(set_lightning_destroy, 3);
}
/* Throw acid on the hapless victim -RAK- */
void
acid_dam(dam, kb_str)
int dam;
const char *kb_str;
{
register int flag;
if (py.flags.acid_resist > 0)
dam = dam / 3;
if (py.flags.resist_acid > 0)
dam = dam / 3;
if (py.flags.acid_im)
dam = 1;
flag = 0;
if (!py.flags.resist_acid)
if (minus_ac((int32u) TR_RES_ACID))
flag = 1;
if (py.flags.acid_resist)
flag += 2;
inven_damage(set_acid_affect, 3);
}